#include "i_thread.h"

namespace idl
{
#ifdef WIN32

DWORD WINAPI ThreadProc(LPVOID lpParam)
{
  ((i_thread*)lpParam)->run();
  return(0);
}

void i_thread::run()
{
  m_thread_func(m_data);
}

i_thread::i_thread() :m_handle(NULL){}

i_thread::~i_thread()
{
  if (m_handle != NULL)
  {
    wait();
    CloseHandle(m_handle);
    m_handle = NULL;
  }
}

bool i_thread::start(void(*thread_func)(void*), void *data)
{
  m_thread_func = thread_func;
  m_data = data;

  m_handle = CreateThread(
    NULL,		/*Default security attributes*/
    0,			/*Use default stack size*/
    ThreadProc,	/*Thread function*/
    this,		/*Argument to thread function*/
    0,			/*Default creation flags*/
    &m_id);

  return  (m_handle != NULL);
}

void i_thread::wait()
{
  if (m_handle != NULL)
  {
    WaitForSingleObject(m_handle, INFINITE);
  }
}

/****************CRITICAL SECTION***************************************************/
i_critical::i_critical()
{
  InitializeCriticalSection(&m_cs);
}

i_critical::~i_critical()
{
  DeleteCriticalSection(&m_cs);
}

void i_critical::enter()
{
  EnterCriticalSection(&m_cs);
}

void i_critical::leave()
{
  LeaveCriticalSection(&m_cs);
}

/****************EVENT***************************************************/
i_event::i_event()
{
  m_ev = CreateEvent(NULL, /*A pointer to a SECURITY_ATTRIBUTES structure.If this parameter is NULL, the handle cannot be inherited by child processes.*/
                     FALSE, /*If this parameter is FALSE, the function creates an auto - reset event object, and system automatically resets the event state to nonsignaled after a single waiting thread has been released.*/
                     FALSE, /*If this parameter is TRUE, the initial state of the event object is signaled; otherwise, it is nonsignaled.*/
                     NULL /*If lpName is NULL, the event object is created without a name*/
                     );
}

i_event::~i_event()
{
  if (m_ev != NULL) CloseHandle(m_ev);
}

void i_event::set()
{
  SetEvent(m_ev);
}

void i_event::unset()
{
  ResetEvent(m_ev);
}

void i_event::wait()
{
  WaitForSingleObject(m_ev, INFINITE);
}

/******************************************ENi_WINDOWS_IMPLEMENTATION**********************************/

#endif
} /*namespace idl*/